JAVA IO

BIO

同步阻塞模式。 线程发起IO请求后,一直阻塞IO,直到缓冲区数据就绪后,再进入下一步操作。

服务端会调用 accept() 方法等待接收客户端的连接的方式监听请求,请求一旦接收到一个连接请求,就可以建立通信套接字在这个通信套接字上进行读写操作,此时不能再接收其他客户端连接请求,只能等待同当前连接的客户端的操作执行完成, 不过可以通过多线程来支持多个客户端的连接。

如果要让 BIO 通信模型 能够同时处理多个客户端请求,就必须使用多线程(socket.accept()socket.read()socket.write() 涉及的三个主要函数都是同步阻塞的)。

NIO

同步非阻塞。同步指的是必须等待IO缓冲区内的数据就绪;非阻塞指,用户线程不原地等待IO缓冲区,可以先做一些其他操作,但是要定时轮询检查IO缓冲区数据是否就绪。

  • 面向缓冲的,基于通道的I/O操作方法。
  • 通过零拷贝的buffer取得数据
  • 通过 channel 在selector(多路复用器)上进行注册
  • 服务端不断轮询 channe l来获取客户端的信息

缓冲区 :IO 面向流(Stream oriented),而 NIO 面向缓冲区(Buffer oriented)

任何时候访问NIO中的数据,都是通过缓冲区进行操作。

而 IO 面向流的,数据直接写入或者将数据直接读到 Stream 对象中。

通道

NIO 通过Channel(通道) 进行读写。

通道是双向的,可读也可写,而流的读写是单向的。无论读写,通道只能和Buffer交互。因为 Buffer,通道可以异步地读写。

选择器

选择器用于使用单个线程处理多个通道,无需切换线程。

读写方式

NIO中的所有IO都是从 Channel(通道) 开始的。

  • 从通道进行数据读取 :创建一个缓冲区,然后请求通道读取数据。
  • 从通道进行数据写入 :创建一个缓冲区,填充数据,并要求通道写入数据。

Buffer

属性

属性 说明
capacity 容量 Buffer 所能容纳数据元素的最大数量,也就是底层数组的容量值。在创建时被指定,不可更改。
position 位置 下一个被读或被写的位置
limit 上界 可供读写的最大位置,用于限制 position,position < limit
mark 标记 位置标记,用于记录某一次的读写位置,可以通过 reset 重新回到这个位置

读写操作

  • 每当写入了一个单位的数据后, position就会递增1
  • 调用了 filp 方法将 Buffer 从写模式转换到读模式时, position 的值会自动被设置为0
  • 每当读取一个单位的数据, position 的值递增1

读写操作都会修改 position 的值,每次读写的位置是当前 position 的下一个位置。通过修改 position,我们可以读取指定位置的数据。

读取刚写完的操作时,需要同时修改 position 和 limit。函数 flip 可以合二为一;

AIO

异步非阻塞。NIO中,仍需用户线程定时轮询IO缓冲区状态。AIO的异步非阻塞IO应该让内核系统完成轮询,等待通知。

字节流与字符流

1个字节(1 byte)= 2个字符

  • 字节流操作的基本单元为字节;字符流操作的基本单元为Unicode码元。
  • 字节流默认不使用缓冲区;字符流使用缓冲区。
  • 字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或读取Unicode码元; 字符流通常处理文本数据,它支持写入及读取Unicode码元。